#pragma  once 
#include<iostream> 
#include<queue>
#include<pthread.h> 
#include"Task.hpp"
#include"Log.hpp"

namespace wyl
{
#define NUM 5
  class ThreadPool
  {
  private:
    int _num;
    std::queue<Task> _TaskQueue; //任务队列
    pthread_mutex_t _lock; //互斥锁 
    pthread_cond_t _cond;//条件变量
    bool _stop ;
    static ThreadPool* instance;

    ThreadPool():_num(NUM) , _stop(false){
      pthread_mutex_init(&_lock,nullptr);
      pthread_cond_init(&_cond,nullptr);
    }
    ThreadPool(const ThreadPool &){}
  public:
  
    //获取单例
    static ThreadPool* GetInstance()
    {
      static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER ; //静态锁
      if(instance == nullptr)
      {
        pthread_mutex_lock(&_mutex) ; 
        if(instance == nullptr) 
        {
          instance = new ThreadPool(); 
          instance->InitPthreadPool();
        }
        pthread_mutex_unlock(&_mutex);
      }
      return instance ;
    }

    //线程池是否在运行
    bool IsStop()
    {
      return _stop; 
    }

    bool TaskQueueIsEmpty()
    {
      return _TaskQueue.size() == 0; 
    }
    
    //加锁
    void Lock()
    {
        pthread_mutex_lock(&_lock);   
    }
    //解锁
    void UnLock()
    {
        pthread_mutex_unlock(&_lock);   
    }

    //等待
    void Wait(){
        pthread_cond_wait(&_cond, &_lock);
    } 
    
    //唤醒 
    void WakeUp()
    {
        pthread_cond_signal(&_cond);
    }

    //线程运行
    static void* ThreadRoutinue(void* args)
    {
        ThreadPool* tp = (ThreadPool*)args; 
        //处理任务
        while(true)
        {
          Task t ; 
          tp->Lock();
          
          //如果队列为空，进入等待
          while(tp->TaskQueueIsEmpty())
          {
            tp->Wait();//消费者等待 
          }
          //拿出任务
          tp->TaskPop(t); 
          tp->UnLock(); 

          //处理任务 
          t();

        }
    }
    
    //线程池初始化
    bool InitPthreadPool()
    {
        for(int i = 0 ; i  < _num ; i ++)
        {
          pthread_t pid ;
          if(pthread_create(&pid,nullptr,ThreadRoutinue,this) != 0)
          {
            LOG(FATAL,"PthreadPool Init Error !") ; 
            return false; 
          }
        }
        LOG(FATAL,"PthreadPool Init Success !") ; 
        return true; 
    }
    
    //推送任务
    void TaskPush(const Task& in) 
    {
        Lock();
        _TaskQueue.push(in);
        UnLock();
        WakeUp(); //唤醒消费者
    }

    //拿出任务
    void TaskPop(Task& out)
    {
      out = _TaskQueue.front();
      _TaskQueue.pop();
    }
    
    ~ThreadPool(){
        pthread_mutex_destroy(&_lock);
        pthread_cond_destroy(&_cond);
    }
  };

 ThreadPool* ThreadPool::instance = nullptr;
};
